﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;
using System.Collections.ObjectModel;
using CodeSample.Model;
using CodeSample.Database;

namespace CodeSample.Utils
{
    public enum SampleSortBy { LANGUAGE, NAME }
    public enum SampleSortOption { ASCENDING, DESCENDING }

    public class DataProcessMan
    {
        private DBAdapterMan adapter;
        private double searchProgress;

        public double SearchProgress
        {
            get { return searchProgress; }
            set { searchProgress = value; }
        }

        public DataProcessMan()
        {
            adapter = new DBAdapterMan("CodeSample Database.mdb", "");
            this.searchProgress = 0;
        }

        public DataProcessMan(string filePath)
        {
            adapter = new DBAdapterMan(filePath, "");
            this.searchProgress = 0;
        }

        public void GetSamples(ref ObservableCollection<SampleMan> samples)
        {
            OleDbDataReader reader = this.adapter.GetTable("Sample");
            samples.Clear();

            while (reader.Read())
            {
                SampleMan sample = new SampleMan(reader.GetValue(0).ToString(),
                    reader.GetValue(1).ToString(), reader.GetValue(2).ToString(),
                    reader.GetValue(3).ToString(),
                    new SampleDescription(reader.GetValue(4).ToString(),
                        reader.GetValue(5).ToString(), reader.GetValue(6).ToString()));
                samples.Add(sample);
            }
        }

        public void GetCategory(ref ObservableCollection<SampleMan> samples, string language)
        {
            language = language.ToUpper();
            samples.Clear();
            this.GetSamples(ref samples);

            for (int i = 0; i < samples.Count; i++)
            {
                if (!samples[i].Language.ToUpper().Equals(language))
                {
                    samples.RemoveAt(i);
                    --i;
                }
            }
        }

        //public List<string> GetLanguages()
        //{
        //    OleDbDataReader reader = this.adapter.GetLanguage();
        //    List<string> languages = new List<string>();

        //    while (reader.Read())
        //    {
        //        languages.Add(reader.GetValue(0).ToString());
        //    }

        //    return languages;
        //}

        public List<string> GetLanguages(ObservableCollection<SampleMan> samples)
        {
            List<string> languages = new List<string>();

            foreach (SampleMan sample in samples)
            {
                if (!IsListContains(languages, sample.Language.ToUpper()))
                    languages.Add(sample.Language);
            }

            return languages;
        }

        private bool IsListContains(List<string> StringList, string aUpperCaseString)
        {
            foreach (string item in StringList)
            {
                if (item.ToUpper().Equals(aUpperCaseString))
                    return true;
            }
            return false;
        }

        public void SortSamples(ref ObservableCollection<SampleMan> samples, SampleSortBy by, SampleSortOption option)
        {
            List<SampleMan> sampleList = new List<SampleMan>();
            foreach (SampleMan sample in samples)
            {
                sampleList.Add(sample);
            }
            
            switch (by)
            {
                case SampleSortBy.NAME:
                    sampleList.Sort(delegate(SampleMan s1, SampleMan s2) { return s1.Name.CompareTo(s2.Name); });
                    break;
                case SampleSortBy.LANGUAGE:
                    sampleList.Sort(delegate(SampleMan s1, SampleMan s2) { return s1.Language.CompareTo(s2.Language); });
                    this.SortInEachCategory(sampleList);
                    break;
                default:
                    break;
            }

            if (option == SampleSortOption.DESCENDING)
                sampleList.Reverse();
            samples.Clear();
            foreach (SampleMan sample in sampleList)
            {
                samples.Add(sample);
            }
        }

        private List<SampleMan> SortInEachCategory(List<SampleMan> sampleList)
        {
            if (sampleList.Count > 0)
            {
                SampleMan sp = new SampleMan();
                int index = 0;
                int pointer = 0;
                int count = 0;
                string currentLanguage = sampleList[0].Language;

                for (; pointer < sampleList.Count; pointer++)
                {
                    if (!currentLanguage.Equals(sampleList[pointer].Language))
                    {
                        count = pointer - index;
                        sampleList.Sort(index, count, sp);
                        index = pointer;
                        count = 0;
                        currentLanguage = sampleList[pointer].Language;
                    }
                }

                count = pointer - index;
                sampleList.Sort(index, count, sp);
            }

            return null;
        }

        public string AddNewSample(SampleMan sample, bool generateRandomID)
        {
            if (generateRandomID)
            {
                string name = sample.Name.Trim();
                string shortName = sample.Name[0].ToString().ToUpper();

                while (name.Contains(' '))
                {
                    shortName += name.Substring(name.IndexOf(' ') + 1, 1).ToUpper();
                    name = name.Substring(name.IndexOf(' ') + 1);
                }

                Random rand = new Random();
                int randomNumber = rand.Next(99999999, 1000000000);

                string ID = string.Format("{0}-{1}-{2}",
                    sample.Language, shortName, randomNumber.ToString());

                sample.Id = ID;
            }

            adapter.InsertSampleRecord(sample);

            return sample.Id;
        }

        public string UpdateSample(SampleMan aSample)
        {
            this.adapter.UpdateSampleRecord(aSample);

            return aSample.Id;
        }

        public void DeleteSample(SampleMan aSample)
        {
            this.adapter.DeleteSampleRecord(aSample);
        }

        public void Search(ref ObservableCollection<SampleMan> samples, string keyword)
        {
            keyword = keyword.ToUpper();

            for (int i = 0; i < samples.Count; i++)
            {
                this.searchProgress = (double)i * 100 / (samples.Count - 1);
                if (!samples[i].isNameContains(keyword) && !samples[i].isDescriptionContains(keyword))
                {
                    samples.RemoveAt(i);
                    --i;
                }
            }
        }

        public void searchDescription(ref ObservableCollection<SampleMan> samples, string keyword)
        {
            keyword = keyword.ToUpper();

            for (int i = 0; i < samples.Count; i++)
            {
                this.searchProgress = (double)i * 100 / (samples.Count - 1);
                if (!samples[i].isDescriptionContains(keyword))
                {
                    samples.RemoveAt(i);
                    --i;
                }
            }
        }

        public int GetIndexOfID(ObservableCollection<SampleMan> samples, string ID)
        {
            for (int i = 0; i < samples.Count; i++)
            {
                if (samples[i].Id.Equals(ID))
                    return i;
            }

            return -1;
        }

        public void CloseConnection()
        {
            this.adapter.CloseConnection();
        }
    }
}
